﻿using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Dapper;
using System.Text.RegularExpressions;

namespace CodeGenerator
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Init();
        }

        /// <summary>
        /// 得到model名称
        /// </summary>
        /// <param name="tableName"></param>
        /// <returns></returns>
        private static string GetModelName(string tableName)
        {
            return "M" + tableName + "Model";
        }

        public static int dbTypeInt = 0; //数据库类型（0：sqlserver；1：mysql）
        public static string connStr = ""; //数据库连接字符串
        public static IDbConnection conn = null;
        private void Init()
        {
            INIBase ib = new INIBase("config.ini");
            string dbTypeIntStr = ib.IniReadValue("dbtype", "index");
            int.TryParse(dbTypeIntStr, out dbTypeInt);

            //sqlserver
            string dbTypeStr = "sqlserver";
            string sqlServerName = ib.IniReadValue(dbTypeStr, "serverName");
            tbxSqlServerServerName.Text = sqlServerName;
            string sqlServerValidateTypeStr = ib.IniReadValue(dbTypeStr, "validateType");
            int sqlServervalidateTypeInt = 0; int.TryParse(sqlServerValidateTypeStr, out sqlServervalidateTypeInt);
            if (sqlServervalidateTypeInt != 0 && sqlServervalidateTypeInt != 1)
            {
                sqlServervalidateTypeInt = 0;
            }
            cbxSqlServerValidateType.SelectedIndex = sqlServervalidateTypeInt;
            switch (sqlServervalidateTypeInt)
            {
                case 0: //windows 身份验证
                    {
                        tbxSqlserverLoginName.Text = "";
                        tbxSqlserverLoginName.Enabled = false;
                        tbxSqlServerPwd.Text = "";
                        tbxSqlServerPwd.Enabled = false;
                    }
                    break;
                case 1: //sql server 身份验证
                    {
                        string sqlserverLoginName = ib.IniReadValue(dbTypeStr, "loginName");
                        string sqlserverLoginPwd = ib.IniReadValue(dbTypeStr, "loginPwd");
                        tbxSqlserverLoginName.Text = sqlserverLoginName;
                        tbxSqlserverLoginName.Enabled = true;
                        tbxSqlServerPwd.Text = sqlserverLoginPwd;
                        tbxSqlServerPwd.Enabled = true;
                    }
                    break;
                default:
                    {
                    }
                    break;
            }

            //mysql
            dbTypeStr = "mysql";
            string mysqlServerName = ib.IniReadValue(dbTypeStr, "serverName");
            string mysqlServerPort = ib.IniReadValue(dbTypeStr, "serverPort");
            string mysqlLoginName = ib.IniReadValue(dbTypeStr, "loginName");
            string mysqlLoginPwd = ib.IniReadValue(dbTypeStr, "loginPwd");
            tbxServerName.Text = mysqlServerName;
            tbxServerPort.Text = mysqlServerPort;
            tbxLoginName.Text = mysqlLoginName;
            tbxLoginPwd.Text = mysqlLoginPwd;

            tabControlConnSelect.SelectedIndex = dbTypeInt;
        }
        /// <summary>
        /// 数据库类型选择
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tabControlConnSelect_SelectedIndexChanged(object sender, EventArgs e)
        {
            dbTypeInt = tabControlConnSelect.SelectedIndex;
            cbxSqlServerTables.Items.Clear();
            cbxDBList.Items.Clear();
            lbxAllTables.Items.Clear();
            lbxGenerateTables.Items.Clear();
        }
        /// <summary>
        /// sqlserver 身份验证更换
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cbxSqlServerValidateType_SelectedIndexChanged(object sender, EventArgs e)
        {
            var selectIndex = cbxSqlServerValidateType.SelectedIndex;
            switch (selectIndex)
            {
                case 0:
                    {
                        tbxSqlserverLoginName.Text = "";
                        tbxSqlserverLoginName.Enabled = false;
                        tbxSqlServerPwd.Text = "";
                        tbxSqlServerPwd.Enabled = false;
                    }
                    break;
                case 1:
                    {
                        INIBase ib = new INIBase("config.ini");
                        string loginName = ib.IniReadValue("sqlserver", "loginName");
                        string loginPwd = ib.IniReadValue("sqlserver", "loginPwd");
                        tbxSqlserverLoginName.Text = loginName;
                        tbxSqlserverLoginName.Enabled = true;
                        tbxSqlServerPwd.Text = loginPwd;
                        tbxSqlServerPwd.Enabled = true;
                    }
                    break;
                default:
                    {
                    }
                    break;
            }
        }


        /// <summary>
        /// 连接/测试
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnConnectionTest_Click(object sender, EventArgs e)
        {
            switch (dbTypeInt)
            {
                case 0: //sqlserver
                    {
                        string serverName1 = tbxSqlServerServerName.Text.Trim();
                        int validateTypeInt = cbxSqlServerValidateType.SelectedIndex;
                        string loginName3 = tbxSqlserverLoginName.Text.Trim();
                        string loginPwd1 = tbxSqlServerPwd.Text.Trim();
                        connStr = GetSqlServerConnStr(validateTypeInt, serverName1, "master", loginName3, loginPwd1);
                    }
                    break;
                case 1: //mysql
                    {
                        string serverName3 = tbxServerName.Text.Trim();
                        string serverPort3 = tbxServerPort.Text.Trim();
                        string loginName3 = tbxLoginName.Text.Trim();
                        string loginPwd3 = tbxLoginPwd.Text.Trim();
                        if (string.IsNullOrWhiteSpace(serverPort3))
                        {
                            serverPort3 = "3306";
                        }
                        connStr = GetMysqlConnStr(serverName3, serverPort3, loginName3, loginPwd3, "information_schema");
                    }
                    break;
                default:
                    break;
            }

            //IDbConnection conn = null;
            string strSQL = "";
            switch (dbTypeInt)
            {
                case 0:
                    {
                        conn = new SqlConnection(connStr);
                        strSQL = string.Format("SELECT Name as dbName FROM Master..SysDatabases ORDER BY Name;");
                    }
                    break;
                case 1:
                    {
                        conn = new MySqlConnection(connStr);
                        strSQL = string.Format("SELECT `SCHEMA_NAME` as dbName FROM `information_schema`.`SCHEMATA`;");
                    }
                    break;
                default:
                    break;
            }
            if (conn == null)
            {
                MessageBox.Show("数据库类型错误");
                return;
            }

            bool isConnected = false;
            List<dynamic> dbList = new List<dynamic>();
            try
            {
                conn.Open();
                if (conn.State == ConnectionState.Open)
                {
                    isConnected = true;
                }
                dbList = conn.Query(strSQL).ToList();
                List<string> hasLi = new List<string>() { "information_schema", "mysql", "performance_schema", "test" };
                dbList.RemoveAll(m => hasLi.Any(k => k == m.dbName));
                conn.Close();
                conn.Dispose();
            }
            catch
            {
            }
            if (isConnected) //连接成功
            {
                switch (dbTypeInt)
                {
                    case 0:
                        {
                            cbxSqlServerTables.Enabled = false;
                            cbxSqlServerTables.Update();
                            Thread.Sleep(100);
                            cbxSqlServerTables.Enabled = true;
                            cbxSqlServerTables.Update();
                            cbxSqlServerTables.Items.Clear();
                            dbList.ForEach(item =>
                            {
                                cbxSqlServerTables.Items.Add(item.dbName);
                            });
                            cbxSqlServerTables.SelectedIndex = 0;

                            string serverName = tbxSqlServerServerName.Text.Trim();
                            int validateTypeInt = cbxSqlServerValidateType.SelectedIndex;
                            string loginName = tbxSqlserverLoginName.Text;
                            string loginPwd = tbxSqlServerPwd.Text.Trim();
                            string dbType = "sqlserver";
                            INIBase ib = new INIBase("config.ini");
                            ib.IniWriteValue("dbtype", "index", dbTypeInt.ToString());
                            ib.IniWriteValue(dbType, "serverName", serverName);
                            ib.IniWriteValue(dbType, "validateType", validateTypeInt.ToString());
                            ib.IniWriteValue(dbType, "loginName", loginName);
                            ib.IniWriteValue(dbType, "loginPwd", loginPwd);
                        }
                        break;
                    case 1:
                        {
                            cbxDBList.Enabled = false;
                            cbxDBList.Update();
                            Thread.Sleep(100);
                            cbxDBList.Enabled = true;
                            cbxDBList.Update();
                            cbxDBList.Items.Clear();
                            dbList.ForEach(item =>
                            {
                                cbxDBList.Items.Add(item.dbName);
                            });
                            cbxDBList.SelectedIndex = 0;

                            string serverName = tbxServerName.Text.Trim();
                            string serverPort = tbxServerPort.Text.Trim();
                            string loginName = tbxLoginName.Text.Trim();
                            string loginPwd = tbxLoginPwd.Text.Trim();
                            string dbType = "mysql";
                            INIBase ib = new INIBase("config.ini");
                            ib.IniWriteValue("dbtype", "index", dbTypeInt.ToString());
                            ib.IniWriteValue(dbType, "serverName", serverName);
                            ib.IniWriteValue(dbType, "serverPort", serverPort);
                            ib.IniWriteValue(dbType, "loginName", loginName);
                            ib.IniWriteValue(dbType, "loginPwd", loginPwd);
                        }
                        break;
                    default:
                        break;
                }

                lbxAllTables.Items.Clear();
                lbxGenerateTables.Items.Clear();
            }
            else
            {
                MessageBox.Show("连接失败1." + dbTypeInt);
            }
        }
        /// <summary>
        /// 连接指定数据库，获取所有表名称
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnGetAllTables_Click(object sender, EventArgs e)
        {
            string dbName = "";
            string strSQL = "";
            //IDbConnection conn = null;
            switch (dbTypeInt)
            {
                case 0:
                    {
                        if (cbxSqlServerTables.SelectedIndex < 0)
                        {
                            MessageBox.Show("请先选择数据库");
                            return;
                        }
                        dbName = cbxSqlServerTables.SelectedItem.ToString();
                        string serverName = tbxSqlServerServerName.Text.Trim();
                        int validateTypeInt = cbxSqlServerValidateType.SelectedIndex;
                        string loginName = tbxSqlserverLoginName.Text.Trim();
                        string loginPwd = tbxSqlServerPwd.Text.Trim();
                        connStr = GetSqlServerConnStr(validateTypeInt, serverName, dbName, loginName, loginPwd);
                        strSQL = string.Format("SELECT Name as tbName FROM " + dbName + "..SysObjects Where XType='U' ORDER BY Name;");
                        conn = new SqlConnection(connStr);
                    }
                    break;
                case 1:
                    {
                        if (cbxDBList.SelectedIndex < 0)
                        {
                            MessageBox.Show("请先选择数据库");
                            return;
                        }
                        dbName = cbxDBList.SelectedItem.ToString();
                        string serverName = tbxServerName.Text.Trim();
                        string serverPort = tbxServerPort.Text.Trim();
                        string loginName = tbxLoginName.Text.Trim();
                        string loginPwd = tbxLoginPwd.Text.Trim();
                        connStr = GetMysqlConnStr(serverName, serverPort, loginName, loginPwd, dbName);
                        strSQL = string.Format("select table_name as tbName from information_schema.tables where table_schema='" + dbName + "' and table_type='base table';");
                        conn = new MySqlConnection(connStr);
                    }
                    break;
                default:
                    break;
            }

            if (connStr == null)
            {
                MessageBox.Show("数据库类型错误！");
                return;
            }

            bool isConnected = false;
            List<dynamic> tableList = new List<dynamic>();
            try
            {
                conn.Open();
                if (conn.State == ConnectionState.Open)
                {
                    isConnected = true;
                }
                tableList = conn.Query(strSQL).ToList();

                //移除带有数字的表名
                tableList.RemoveAll(m => Regex.IsMatch(m.tbName, @"\d+"));

                conn.Close();
                //conn.Dispose();
            }
            catch
            {
            }

            if (isConnected) //连接成功
            {
                lbxAllTables.Items.Clear();
                lbxGenerateTables.Items.Clear();
                tableList.ForEach(item =>
                {
                    lbxAllTables.Items.Add(item.tbName);
                });
            }
            else
            {
                MessageBox.Show("连接失败2." + dbTypeInt);
            }
        }


        private void btnRightSingle_Click(object sender, EventArgs e)
        {
            var selectedItems = lbxAllTables.SelectedItems;
            if (selectedItems == null)
            {
                return;
            }
            List<object> list = new List<object>();
            foreach (var selectedItem in selectedItems)
            {
                list.Add(selectedItem);
                if (lbxGenerateTables.Items.IndexOf(selectedItem) < 0)
                {
                    lbxGenerateTables.Items.Add(selectedItem);
                }
            }
            foreach (var selectedItem in list)
            {
                lbxAllTables.Items.Remove(selectedItem);
            }
        }

        private void btnRightAll_Click(object sender, EventArgs e)
        {
            foreach (var item in lbxAllTables.Items)
            {
                string itemStr = item.ToString();
                if (lbxGenerateTables.Items.IndexOf(itemStr) < 0)
                {
                    lbxGenerateTables.Items.Add(itemStr);
                }
            }
            lbxAllTables.Items.Clear();
        }

        private void btnLeftSingle_Click(object sender, EventArgs e)
        {
            var selectedItems = lbxGenerateTables.SelectedItems;

            if (selectedItems == null)
            {
                return;
            }
            List<object> list = new List<object>();
            foreach (var selectedItem in selectedItems)
            {
                list.Add(selectedItem);
                if (lbxAllTables.Items.IndexOf(selectedItem) < 0)
                {
                    lbxAllTables.Items.Add(selectedItem);
                }
            }
            foreach (var selectedItem in list)
            {
                lbxGenerateTables.Items.Remove(selectedItem);
            }
        }

        private void btnLeftAll_Click(object sender, EventArgs e)
        {
            foreach (var item in lbxGenerateTables.Items)
            {
                string itemStr = item.ToString();
                if (lbxAllTables.Items.IndexOf(itemStr) < 0)
                {
                    lbxAllTables.Items.Add(itemStr);
                }
            }
            lbxGenerateTables.Items.Clear();
        }

        /// <summary>
        /// 生成model文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnGenerateModel_Click(object sender, EventArgs e)
        {
            if (lbxGenerateTables.Items.Count <= 0)
            {
                MessageBox.Show("请选择要生成的表名称");
                return;
            }
            List<string> tableList = new List<string>();
            foreach (var item in lbxGenerateTables.Items)
            {
                tableList.Add(item.ToString());
            }

            var dirpath = tbxFolderPath.Text;
            if (string.IsNullOrWhiteSpace(dirpath))
            {
                MessageBox.Show("请选择文件夹");
                return;
            }

            IDbConnection conn = null;
            string dbTypeStr = "";
            switch (dbTypeInt)
            {
                case 0:
                    {
                        conn = new SqlConnection(connStr);
                        dbTypeStr = "sqlserver";
                    }
                    break;
                case 1:
                    {
                        conn = new MySqlConnection(connStr);
                        dbTypeStr = "mysql";
                    }
                    break;
                default:
                    break;
            }
            if (connStr == null)
            {
                MessageBox.Show("数据库类型错误！");
                return;
            }

            //生成初始化表的文件
            StringBuilder sbrInitTable = new StringBuilder();
            foreach (var item in tableList)
            {
                sbrInitTable.Append("truncate table " + item + ";" + Environment.NewLine);
            }
            string initTableFileName = Path.Combine(dirpath, "initAllTableSql_" + dbTypeStr + ".txt");
            //using (FileStream fs = new FileStream(initTableFileName, FileMode.Create))
            //{
            //	fs.Flush(true);
            //	byte[] buffer = Encoding.UTF8.GetBytes(sbrInitTable.ToString());
            //	fs.Write(buffer, 0, buffer.Length);
            //}

            FileHelper.Write(initTableFileName, sbrInitTable.ToString(), Encoding.UTF8);

            var path = Path.Combine(dirpath, "Model_" + dbTypeStr);
            if (Directory.Exists(path))
            {
                Directory.Delete(path, true);
            }
            Directory.CreateDirectory(path);

            conn.Open();
            string strSQL = "";
            for (int g = 0; g < tableList.Count(); g++)
            {
                var tableName = tableList[g];
                tableName = tableName.Substring(0, 1).ToUpper() + tableName.Substring(1);

                //生成单个文件
                StringBuilder sbr = new StringBuilder();
                StringBuilder sbrInit = new StringBuilder();
                StringBuilder sbrProp = new StringBuilder();
                sbr.Append("using System;" + Environment.NewLine);
                sbr.Append("namespace ZKModel.Model" + Environment.NewLine);
                sbr.Append("{" + Environment.NewLine);
                sbr.Append(GetTab(1) + "/// <summary>" + Environment.NewLine);
                sbr.Append(GetTab(1) + "/// " + Environment.NewLine);
                sbr.Append(GetTab(1) + "/// </summary>" + Environment.NewLine);
                sbr.AppendFormat(GetTab(1) + "public partial class {0}" + Environment.NewLine, GetModelName(tableName));
                sbr.Append(GetTab(1) + "{" + Environment.NewLine);

                switch (dbTypeInt)
                {
                    case 0:
                        {
                            strSQL = string.Format(@"select a.name as columnName, b.name as dataType, isnull(g.[value], '') as columnComment
								from syscolumns a
									left join systypes b on a.xusertype = b.xusertype
									inner join sysobjects d on a.id = d.id and d.xtype = 'U' and d.name <> 'dtproperties'
									left join sys.extended_properties g on a.id = g.major_id and a.colid = g.minor_id
								where d.name = '{0}'
								order by a.id, a.colorder;", tableName);
                        }
                        break;
                    case 1:
                        {
                            strSQL = "select COLUMN_NAME as columnName,DATA_TYPE as dataType, COLUMN_COMMENT as columnComment from INFORMATION_SCHEMA.Columns where table_schema='" + cbxDBList.SelectedItem.ToString() + "' and table_name='" + tableName + "' ;";
                        }
                        break;
                    default:
                        break;
                }
                sbrInit.Append(GetTab(2) + "/// <summary>" + Environment.NewLine);
                sbrInit.Append(GetTab(2) + "/// " + Environment.NewLine);
                sbrInit.Append(GetTab(2) + "/// </summary>" + Environment.NewLine);
                sbrInit.Append(GetTab(2) + "public " + GetModelName(tableName) + "()" + Environment.NewLine);
                sbrInit.Append(GetTab(2) + "{" + Environment.NewLine);



                var tbList = conn.Query(strSQL).ToList();
                int countInt = 0; //计数，方便查找错误
                foreach (var tbInfo in tbList)
                {
                    countInt += 1;
                    var columnName = tbInfo.columnName;
                    var dataType = tbInfo.dataType;
                    var columnComment = tbInfo.columnComment;

                    switch (dbTypeInt) //数据库类型（0：sqlserver；1：mysql）
                    {
                        case 0: //sqlserver
                            {
                                string newTypeStr = GetTypeFormSqlServerToCSharp(dataType);//注意：更改此处，增加类型
                                var realTypeStr = GetRealTypeStr(newTypeStr);
                                sbrInit.AppendFormat(GetTab(3) + columnName + " = " + DefaultForType(Type.GetType(realTypeStr), countInt, dataType, realTypeStr) + ";" + Environment.NewLine);
                                sbrProp.Append(GetTab(2) + "/// <summary>" + Environment.NewLine);
                                sbrProp.Append(GetTab(2) + "/// " + (!string.IsNullOrWhiteSpace(columnComment) ? columnComment : columnName) + Environment.NewLine);
                                sbrProp.Append(GetTab(2) + "/// </summary>" + Environment.NewLine);
                                //sbrProp.Append(GetTab(2) + "public " + newTypeStr + " " + columnName + " { get; set; }" + Environment.NewLine);
                                sbrProp.Append(GetTab(2) + "public " + newTypeStr + " " + columnName + ";" + Environment.NewLine);
                            }
                            break;
                        case 1: //mysql
                            {
                                string newTypeStr = GetTypeFormMySqlToCSharp(dataType); //注意：更改此处，增加类型
                                var realTypeStr = GetRealTypeStr(newTypeStr);
                                sbrInit.AppendFormat(GetTab(3) + columnName + " = " + DefaultForType(Type.GetType(realTypeStr), countInt, dataType, realTypeStr) + ";" + Environment.NewLine);
                                sbrProp.Append(GetTab(2) + "/// <summary>" + Environment.NewLine);
                                sbrProp.Append(GetTab(2) + "/// " + (!string.IsNullOrWhiteSpace(columnComment) ? columnComment : columnName) + Environment.NewLine);
                                sbrProp.Append(GetTab(2) + "/// </summary>" + Environment.NewLine);
                                //sbrProp.Append(GetTab(2) + "public " + newTypeStr + " " + columnName + " { get; set; }" + Environment.NewLine);
                                sbrProp.Append(GetTab(2) + "public " + newTypeStr + " " + columnName + ";" + Environment.NewLine);
                            }
                            break;
                        default:
                            break;
                    }
                }
                sbrInit.Append(GetTab(2) + "}" + Environment.NewLine);
                sbr.Append(sbrInit);
                sbr.Append(sbrProp);
                sbr.Append(GetTab(1) + "}" + Environment.NewLine);
                sbr.Append("}" + Environment.NewLine);
                var fileContent = sbr.ToString();

                string fileName = Path.Combine(path, GetModelName(tableName) + ".cs");
                //using (FileStream fs = new FileStream(fileName, FileMode.Create))
                //{
                //	byte[] buffer = Encoding.UTF8.GetBytes(fileContent);
                //	fs.Write(buffer, 0, buffer.Length);
                //}
                FileHelper.Write(fileName, fileContent, Encoding.UTF8);
            }
            conn.Close();
            conn.Dispose();
            MessageBox.Show("生成成功");
            System.Diagnostics.Process.Start(Path.Combine(dirpath, "Model_" + dbTypeStr));
        }

        /// <summary>
        /// 得到默认值
        /// </summary>
        /// <param name="targetType"></param>
        /// <returns></returns>
        public static object DefaultForType(Type targetType, int countInt, dynamic dataType, string realTypeStr)
        {
            try
            {
                object defaultVal = null;
                if (targetType.IsValueType)
                {
                    switch (targetType.FullName)
                    {
                        case "System.Boolean": defaultVal = "false"; break;
                        //case "System.DateTimeOffset1": defaultVal = "new DateTimeOffset1(new DateTime(1900, 1, 1))"; break;
                        case "System.DateTime": defaultVal = "new DateTime(1900, 1, 1)"; break;
                        case "System.Guid": defaultVal = "new Guid()"; break;
                        default: defaultVal = Activator.CreateInstance(targetType); break;
                    }
                }
                else
                {
                    switch (targetType.FullName)
                    {
                        case "System.String": defaultVal = "\"\""; break;
                    }
                }
                return defaultVal;
            }
            catch (Exception ex)
            {
                string txt = String.Format(@"countInt:【{0}】,dataType:【{1}】,realTypeStr:【{2}】", countInt, dataType, realTypeStr);
                throw new Exception(txt);
            }
        }
        /// <summary>
        /// 从sqlserver数据库中的字段类型转化为C#类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetTypeFormSqlServerToCSharp(string type)
        {
            //从数据库中的字段类型转化为C#普通类型
            string newType = type;
            switch (type)
            {
                case "int": newType = "int"; break;
                case "bit": newType = "int"; break;
                case "varchar": newType = "string"; break;
                case "nvarchar": newType = "string"; break;
                case "text": newType = "string"; break;
                case "time": newType = "DateTime"; break;
                case "date": newType = "DateTime"; break;
                case "datetime": newType = "DateTime"; break;
                case "tinyint": newType = "int"; break;
                case "bigint": newType = "long"; break;
                case "char": newType = "string"; break;
                case "nchar": newType = "string"; break;
                case "float": newType = "float"; break;
                case "binary": newType = "byte"; break;
                case "uniqueidentifier": newType = "Guid"; break;
            }
            return newType;
        }
        /// <summary>
        /// 从mysql数据库中的字段类型转化为C#类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetTypeFormMySqlToCSharp(string type)
        {
            //从数据库中的字段类型转化为C#普通类型
            string newType = type;
            switch (type)
            {
                case "tinyint": newType = "int"; break;
                case "binary": newType = "byte"; break;
                case "int": newType = "int"; break;
                case "bigint": newType = "long"; break;
                case "decimal": newType = "decimal"; break;
                case "double": newType = "double"; break;
                case "char": newType = "char"; break;
                case "varchar": newType = "string"; break;
                case "text": newType = "string"; break;
                case "date": newType = "DateTime"; break;
                case "datetime": newType = "DateTime"; break;
                case "bit": newType = "int"; break;
                //case "bool": newType = "bool"; break;
                case "smallint": newType = "int"; break;
                case "float": newType = "float"; break;
            }
            return newType;
        }

        /// <summary>
        /// 从普通的C#类型转化为‘命名空间+类名’
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetRealTypeStr(string type)
        {
            string newType = type;
            switch (type)
            {
                case "bool": newType = "System.Boolean"; break;
                case "byte": newType = "System.Byte"; break;
                case "int": newType = "System.Int32"; break;
                case "long": newType = "System.Int64"; break;
                case "decimal": newType = "System.Decimal"; break;
                case "float": newType = "System.Single"; break;
                case "double": newType = "System.Double"; break;
                case "char": newType = "System.Char"; break;
                case "string": newType = "System.String"; break;
                case "DateTime": newType = "System.DateTime"; break;
                case "Guid": newType = "System.Guid"; break;
            }
            return newType;
        }

        public static string GetTab(int num)
        {
            string str = "";
            for (int i = 0; i < num; i++)
            {
                str += "	";
            }
            return str;
        }

        private void btnSelectFolder_Click(object sender, EventArgs e)
        {
            folderBrowserDialog.ShowDialog();
            var path = folderBrowserDialog.SelectedPath;
            tbxFolderPath.Text = path;
        }

        /// <summary>
        /// 获取mysql连接字符串
        /// </summary>
        /// <param name="serverName"></param>
        /// <param name="serverPort"></param>
        /// <param name="loginName"></param>
        /// <param name="loginPwd"></param>
        /// <param name="dbName"></param>
        /// <returns></returns>
        string GetMysqlConnStr(string serverName, string serverPort, string loginName, string loginPwd, string dbName)
        {
            return string.Format("Data Source={0};port={1};user id={2};password={3};Initial Catalog={4};Charset=utf8",
                serverName, serverPort, loginName, loginPwd, dbName);
        }

        /// <summary>
        /// 获取sqlserver连接字符串
        /// </summary>
        /// <param name="validateType"></param>
        /// <param name="serverName"></param>
        /// <param name="dbName"></param>
        /// <param name="loginName"></param>
        /// <param name="loginPwd"></param>
        /// <returns></returns>
        string GetSqlServerConnStr(int validateType, string serverName, string dbName, string loginName = "", string loginPwd = "")
        {
            string connStr = "";
            switch (validateType)
            {
                case 0: //windows验证
                    {
                        connStr = string.Format(@"Server = {0};Database = {1};Trusted_Connection = True;",
                            serverName, dbName);
                    }
                    break;
                case 1: //sqlserver验证
                    {
                        connStr = string.Format(@"Data Source = {0};Initial Catalog = {1};User Id = {2};Password = {3};",
                            serverName, dbName, loginName, loginPwd);
                    }
                    break;
                default:
                    break;
            }
            return connStr;
        }

        private void btn_gmodel_Click(object sender, EventArgs e)
        {
            var sql = tbx_sql.Text;
            if (sql.IsNullOrWhiteSpace())
            {
                MessageBox.Show("请填写要生成的sql");
                return;
            }
            DataTable dt = null;


            try
            {
                conn.Open();
                dt = conn.ExecuteReader(sql).GetSchemaTable();
            }
            catch (Exception ex)
            {
                MessageBox.Show("异常：" + ex.ToString());
                conn.Close();
                return;
            }
            conn.Close();

            //得到dyModel的键和类型
            //var type= (Type)(dyModel.GetType());
            //var h= dyModel[0];
            //var type1 = dyModel.GetType();
            // var props= type1.GetProperties();
            //foreach (var prop in props)
            //{
            //    var name = prop.Name;
            //    var type = prop.PropertyType.FullName;
            //}

            StringBuilder sbr = new StringBuilder();
            //dt.Columns
            string clsName = $"{ Guid.NewGuid().ToString("N") }_Info";
            sbr.AppendLine($"namespace ZKModel.Model");
            sbr.AppendLine($"{{");
            sbr.AppendLine($"{GetTab(1)}public partial class {clsName}");
            sbr.AppendLine($"{GetTab(1)}{{");
            sbr.AppendLine($"{GetTab(2)}public {clsName}()");
            sbr.AppendLine($"{GetTab(2)}{{");

            for (int i = 0; i < dt.Rows.Count; i++)
            {
                var row = dt.Rows[i];
                sbr.AppendLine($"{GetTab(3)}{row["ColumnName"]} = default({row["DataType"]});");
            }

            sbr.AppendLine($"{GetTab(2)}}}");
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                var row = dt.Rows[i];
                sbr.AppendLine($"{GetTab(2)}public {row["DataType"]} {row["ColumnName"]};");
            }
            sbr.AppendLine($"{GetTab(1)}}}");
            sbr.AppendLine($"}}");

            var dirpath = tbxFolderPath.Text;
            if (string.IsNullOrWhiteSpace(dirpath))
            {
                MessageBox.Show("请选择文件夹");
                return;
            }

            string sqlPath = Path.Combine(dirpath, "sqlModel");
            if (Directory.Exists(sqlPath))
            {
                Directory.Delete(sqlPath,true);
            }
            Directory.CreateDirectory(sqlPath);
            FileHelper.Write(Path.Combine(sqlPath, clsName +".cs"), sbr.ToString(), Encoding.UTF8);
            MessageBox.Show("sqlModel生成成功！");
            System.Diagnostics.Process.Start(sqlPath);
        }

        private class KeyAndType
        {
            public string Key { get; set; }
            public string Type { get; set; }
        }
    }
}
